use anyhow::{anyhow, Result};
use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
use dotenv::var;
use tracing::info;

type PgPool = Pool<ConnectionManager<PgConnection>>;

#[derive(Clone)]
pub struct Db(PgPool);

impl Db {
    pub fn new(pool_size: u32) -> Result<Self> {
        let db_url = var("DATABASE_URL")?;
        info!("DATABASE_URL -- {}", db_url.clone());
        let pool =
            build_pool(&db_url, pool_size).expect(&format!("Error connecting to {}", db_url));
        Ok(Self(pool))
    }

    pub fn connect(&self) -> Result<PooledConnection<ConnectionManager<PgConnection>>> {
        self.0.get().map_err(|e| anyhow!(e))
    }
}

fn build_pool(database_url: &str, size: u32) -> Result<PgPool> {
    let manager = ConnectionManager::<PgConnection>::new(database_url);
    diesel::r2d2::Pool::builder()
        .max_size(size)
        .min_idle(Some(size))
        .test_on_check_out(false)
        .idle_timeout(None)
        .max_lifetime(None)
        .build(manager).map_err(|e| anyhow!(e))
}
